home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
boot
/
decprom
/
fsDisk.tmp
< prev
next >
Wrap
Text File
|
1990-06-28
|
17KB
|
503 lines
/*
* fsDisk.c --
*
* Routines related to managing local disks. Each partition of a local
* disk (partitions are defined by a table on the disk header) is
* called a ``domain''. FsAttachDisk attaches a domain into the file
* system, and FsDeattachDisk removes it. A domain is given
* a number the first time it is ever attached. This is recorded on
* the disk so it doesn't change between boots. The domain number is
* used to identify disks, and a domain number plus a file number is
* used to identify files. Fsdm_DomainFetch is used to get the state
* associated with a disk, and Fsdm_DomainRelease releases the reference
* on the state. FsDetachDisk checks the references on domains in
* the normal (non-forced) case so that active disks aren't detached.
*
* Copyright 1987 Regents of the University of California
* All rights reserved.
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifdef notdef
static char rcsid[] = "$Header: /sprite/src/boot/decprom/RCS/fsDisk.c,v 1.1 90/02/16 16:14:11 shirriff Exp Locker: shirriff $ SPRITE (Berkeley)";
#endif not lint
#include "sprite.h"
#include "fsBoot.h"
#include "kernel/devDiskLabel.h"
#include "kernel/dev.h"
#include "kernel/devFsOpTable.h"
#include "kernel/machMon.h"
/*
* fsDevice is copied into all Fsio_FileIOHandles. It is used by the drivers
* to get to the partition and geometry information for the disk.
*/
Fs_Device fsDevice;
/*
* fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
*/
static Fsdm_Domain fsDomain;
Fsdm_Domain *fsDomainPtr = &fsDomain;
static Fsio_FileIOHandle fsRootHandle;
Fsio_FileIOHandle *fsRootHandlePtr = &fsRootHandle;
/*
* Forward declarations.
*/
static int InstallLocalDomain();
void AddDomainFlags();
static Boolean IsDecLabel();
/*
*----------------------------------------------------------------------
*
* FsAttachDisk --
*
* Make a particular local disk partition correspond to a prefix.
* This makes sure the disk is up, reads the domain header,
* and calls the initialization routine for the block I/O module
* of the disk's driver. By the time this is called the device
* initialization routines have already been called from Dev_Config
* so the device driver knows how the disk is partitioned into
* domains. This routine sees if the domain is formatted correctly,
* and if so attaches it to the set of domains.
*
* Results:
* SUCCESS if the disk was readable and had a good domain header.
*
* Side effects:
* Sets up the Fsdm_DomainInfo for the domain.
*
*----------------------------------------------------------------------
*/
ReturnStatus
FsAttachDisk(fsDevicePtr)
Fs_Device *fsDevicePtr; /* Global FS device descriptor */
{
ReturnStatus status; /* Error code */
register Address buffer; /* Read buffer */
int headerSector; /* Starting sector of domain header */
int numHeaderSectors; /* Number of sectors in domain header */
int summarySector; /* Sector of summary information. */
Fsdm_SummaryInfo *summaryInfoPtr; /* Pointer to summary info. */
int amountRead; /* Returned from read call */
int devType; /* Device type index */
/*
* Open the raw disk device so we can grub around in the header info.
*/
Mach_MonPrintf("FsAttachDisk: ptr = %x\n", fsDevicePtr);
devType = DEV_TYPE_INDEX(fsDevicePtr->type);
status = (*devFsOpTable[devType].open)(&fsDevice);
if (status != SUCCESS) {
Mach_MonPrintf("Failure\n");
return(status);
}
Mach_MonPrintf("Mallocing\n");
buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
Mach_MonPrintf("Done mallocing\n");
/*
* Read the 31st sector of the partition. It has a copy of the
* 31st sector of the whole disk which describes how the rest of the
* domain's zero'th cylinder is layed out.
*/
status = (*devFsOpTable[devType].read)(&fsDevice,
DEC_LABEL_SECTOR*DEV_BYTES_PER_SECTOR,
DEV_BYTES_PER_SECTOR, buffer, &amountRead);
if (status != SUCCESS) {
#ifndef NO_PRINTF
Mach_MonPrintf("label (sector 31) read fail\n");
#endif
return(status);
}
Mach_MonPrintf("Checking format\n");
/*
* Check for different disk formats, and figure out how the rest
* of the zero'th cylinder is layed out.
*/
if (((Dec_DiskLabel *)buffer)->magic != DEC_LABEL_MAGIC) {
#ifndef NO_PRINTF
Mach_MonPrintf("Bad magic <%x>\n", ((Dec_DiskLabel *)buffer)->magic);
#endif
}
headerSector = ((Dec_DiskLabel *)buffer)->domainSector;
numHeaderSectors = ((Dec_DiskLabel *)buffer)->numDomainSectors;
/*
* Read the domain header and save it with the domain state.
*/
buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * numHeaderSectors);
status = (*devFsOpTable[devType].read)(&fsDevice,
headerSector * DEV_BYTES_PER_SECTOR,
numHeaderSectors * DEV_BYTES_PER_SECTOR,
buffer, &amountRead);
Mach_MonPrintf("Read header\n");
if (status != SUCCESS) {
#ifndef NO_PRINTF
Mach_MonPrintf("Domain fail\n");
#endif
return(status);
} else if (((Fsdm_DomainHeader *)buffer)->magic != FSDM_DOMAIN_MAGIC) {
#ifndef NO_PRINTF
Mach_MonPrintf("Bad magic <%x>\n",
((Fsdm_DomainHeader *)buffer)->magic);
#endif
return(FAILURE);
}
fsDomainPtr->headerPtr = (Fsdm_DomainHeader *) buffer;
/*
* Set up the ClientData part of *devicePtr to reference the
* Fsdm_Geometry part of the domain header. This is used by the
* block I/O routines.
*/
fsDevicePtr->data = (ClientData)&fsDomainPtr->headerPtr->geometry;
/*
* Set up a file handle for the root directory. What is important
* is the device info (for Block IO) and the file descriptor itself.
*/
Mach_MonPrintf("Init'ing handle\n");
FsInitFileHandle(fsDomainPtr, FSDM_ROOT_FILE_NUMBER, fsRootHandlePtr);
Mach_MonPrintf("Done\n");
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* IsSunLabel --
*
* Poke around in the input buffer and see if it looks like
* a Sun format disk label.
*
* Results:
* TRUE or FALSE
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef notdef
static Boolean
IsSunLabel(buffer)
Address buffer; /* Buffer containing zero'th sector */
{
register Sun_DiskLabel *sunLabelPtr;
sunLabelPtr = (Sun_DiskLabel *)buffer;
if (sunLabelPtr->magic == SUN_DISK_MAGIC) {
/*
* Should check checkSum...
*/
return(TRUE);
} else {
return(FALSE);
}
}
#endif
/*
*----------------------------------------------------------------------
*
* IsSpriteLabel --
*
* Poke around in the input buffer and see if it looks like
* a Sprite format disk header.
*
* Results:
* TRUE or FALSE
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef notdef
static Boolean
IsSpriteLabel(buffer)
Address buffer; /* Buffer containing zero'th sector */
{
register FsDiskHeader *diskHeaderPtr;
register int index;
register int checkSum;
diskHeaderPtr = (FsDiskHeader *)buffer;
if (diskHeaderPtr->magic == FSDM_DISK_MAGIC) {
return(TRUE);
}
}
return(FALSE);
}
#endif
/*
*----------------------------------------------------------------------
* The following routines are used by device drivers to map from block
* and sector numbers to disk addresses. There are two sets, one for
* drivers that use logical sector numbers (i.e. SCSI) and the other
* for <cyl,head,sector> format disk addresses.
*----------------------------------------------------------------------
*/
/*
*----------------------------------------------------------------------
*
* Fs_BlocksToSectors --
*
* Convert from block indexes (actually, fragment indexes) to
* sectors using the geometry information on the disk. This
* is a utility for block device drivers.
*
* Results:
* The sector number that corresponds to the fragment index.
* The caller has to make sure that its I/O doesn't cross a
* filesystem block boundary.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#define SECTORS_PER_FRAG (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
#if defined(SCSI_DISK_BOOT) || defined(SUN_PROM_BOOT)
int
Fs_BlocksToSectors(fragNumber, data)
int fragNumber; /* Fragment index to map into block index */
ClientData data; /* ClientData from the device info */
{
register Fsdm_Geometry *geoPtr;
register int sectorNumber; /* The sector corresponding to the fragment */
register int cylinder; /* The cylinder number of the fragment */
register int rotationalSet; /* The rotational set with cylinder of frag */
register int blockNumber; /* The block number within rotational set */
geoPtr = (Fsdm_Geometry *)data;
blockNumber = fragNumber / FS_FRAGMENTS_PER_BLOCK;
cylinder = blockNumber / geoPtr->blocksPerCylinder;
if (geoPtr->rotSetsPerCyl > 0) {
/*
* Do fancy rotational set mapping.
*/
blockNumber -= cylinder * geoPtr->blocksPerCylinder;
rotationalSet = blockNumber / geoPtr->blocksPerRotSet;
blockNumber -= rotationalSet * geoPtr->blocksPerRotSet;
sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
rotationalSet +
geoPtr->blockOffset[blockNumber];
sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
} else {
/*
* Do straight-forward mapping.
*/
sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
fragNumber * SECTORS_PER_FRAG - cylinder *
geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
SECTORS_PER_FRAG;
}
return(sectorNumber);
}
#endif
/*
*----------------------------------------------------------------------
*
* Fs_BlocksToDiskAddr --
*
* Convert from block indexes (actually, fragment indexes) to
* disk address (head, cylinder, sector) using the geometry information
* on the disk. This is a utility for block device drivers.
*
* Results:
* The disk address that corresponds to the disk address.
* The caller has to make sure that its I/O doesn't cross a
* filesystem block boundary.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef XYLOGICS_BOOT
void
Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
int fragNumber; /* Fragment index to map into block index */
ClientData data; /* ClientData from the device info */
Dev_DiskAddr *diskAddrPtr;
{
register Fsdm_Geometry *geoPtr;
register int sectorNumber; /* The sector corresponding to the fragment */
register int cylinder; /* The cylinder number of the fragment */
register int rotationalSet; /* The rotational set with cylinder of frag */
register int blockNumber; /* The block number within rotational set */
geoPtr = (Fsdm_Geometry *)data;
/*
* Map to block number because the rotational sets are laid out
* relative to blocks. After that the cylinder is easy because we know
* blocksPerCylinder. To get the head and sector we first get the
* rotational set (described in fsDisk.h) of the block and the
* block's sector offset (relative to the rotational set!). This complex
* algorithm crops up because there isn't necessarily an even number
* of blocks per track. The 'blockOffset' array in the geometry gives
* a sector index of each successive block in a rotational set. Finally,
* we can use the sectorsPerTrack to get the head and sector.
*/
blockNumber = fragNumber / FS_FRAGMENTS_PER_BLOCK;
cylinder = blockNumber / geoPtr->blocksPerCylinder;
blockNumber -= cylinder * geoPtr->blocksPerCylinder;
diskAddrPtr->cylinder = cylinder;
rotationalSet = blockNumber / geoPtr->blocksPerRotSet;
blockNumber -= rotationalSet * geoPtr->blocksPerRotSet;
/*
* The follow statment had to be broken into two because the compiler used
* register d2 to do the modulo operation, but wasn't saving its value.
*/
sectorNumber = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
rotationalSet + geoPtr->blockOffset[blockNumber];
sectorNumber +=
(fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
diskAddrPtr->head = sectorNumber / geoPtr->sectorsPerTrack;
diskAddrPtr->sector = sectorNumber -
diskAddrPtr->head * geoPtr->sectorsPerTrack;
}
#endif
/*
*----------------------------------------------------------------------
*
* Fs_SectorsToRawDiskAddr --
*
* Convert from a sector offset to a raw disk address (cyl, head,
* sector) using the geometry information on the disk. This is a
* utility for raw device drivers and does not pay attention to the
* rotational position of filesystem disk blocks.
*
* This should be moved to Dev
*
* Results:
* The disk address that corresponds exactly to the byte offset.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef XYLOGICS_BOOT
int
Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
int sector; /* Sector number (counting from zero 'til the total
* number of sectors in the disk) */
int numSectors; /* Number of sectors per track */
int numHeads; /* Number of heads on the disk */
Dev_DiskAddr *diskAddrPtr;
{
register int sectorsPerCyl; /* The rotational set with cylinder of frag */
sectorsPerCyl = numSectors * numHeads;
diskAddrPtr->cylinder = sector / sectorsPerCyl;
sector -= diskAddrPtr->cylinder * sectorsPerCyl;
diskAddrPtr->head = sector / numSectors;
diskAddrPtr->sector = sector - numSectors * diskAddrPtr->head;
}
#endif
/*
*----------------------------------------------------------------------
*
* FsDeviceBlockIO --
*
* Map a file system block address to a block device block address
* perform the requested operation.
*
* NOTE: This routine is temporary and should be replaced when the file system
* is converted to use the async block io interface.
*
* Results:
* The return status of the operation.
*
* Side effects:
* Blocks may be written or read.
*
*----------------------------------------------------------------------
*/
ReturnStatus
FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
int readWriteFlag; /* FS_READ or FS_WRITE */
Fs_Device *devicePtr; /* Specifies device type to do I/O with */
int fragNumber; /* CAREFUL, fragment index, not block index.
* This is relative to start of device. */
int numFrags; /* CAREFUL, number of fragments, not blocks */
Address buffer; /* I/O buffer */
{
ReturnStatus status; /* General return code */
int firstSector; /* Starting sector of transfer */
DevBlockDeviceRequest request;
int transferCount;
int devType;
devType = DEV_TYPE_INDEX(devicePtr->type);
if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
/*
* The I/O doesn't start on a block boundary. Transfer the
* first few extra fragments to get things going on a block boundary.
*/
register int extraFrags;
extraFrags = FS_FRAGMENTS_PER_BLOCK -
(fragNumber % FS_FRAGMENTS_PER_BLOCK);
if (extraFrags > numFrags) {
extraFrags = numFrags;
}
firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
status = (*devFsOpTable[devType].read)(devicePtr,
firstSector * DEV_BYTES_PER_SECTOR,
extraFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
if (status != SUCCESS) {
#ifndef NO_PRINTF
Mach_MonPrintf("Fragment read failure\n");
#endif
}
extraFrags = transferCount / FS_FRAGMENT_SIZE;
fragNumber += extraFrags;
buffer += transferCount;
numFrags -= extraFrags;
}
if (numFrags > 0) {
/*
* Transfer the left over fragments.
*/
firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
status = (*devFsOpTable[devType].read)(devicePtr,
firstSector * DEV_BYTES_PER_SECTOR,
numFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
if (status != SUCCESS) {
#ifndef NO_PRINTF
Mach_MonPrintf("Last fragment read failure\n");
#endif
}
}
return(status);
}